package cn.hg.jbsa.admin.controller.system;

import java.sql.SQLException;
import java.util.Date;

import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.authz.annotation.RequiresPermissions;

import com.jfinal.aop.Before;
import com.jfinal.aop.Inject;
import com.jfinal.kit.Kv;
import com.jfinal.log.Log;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.IAtom;
import com.jfinal.plugin.activerecord.Page;

import cn.hg.jbsa.admin.controller.BaseJbsaAdminController;
import cn.hg.jbsa.admin.controller.system.validator.JbsaDictValidator;
import cn.hg.jbsa.admin.model.JbsaAdmin;
import cn.hg.jbsa.admin.model.JbsaDict;
import cn.hg.jbsa.admin.service.JbsaDictService;
import cn.hg.jbsa.common.annotation.JbsaLog;
import cn.hg.jbsa.common.constant.JbsaConstants;
import cn.hg.jbsa.common.web.LayuiPage;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ObjectUtil;
import io.jboot.components.cache.annotation.CacheEvict;
import io.jboot.db.model.Columns;
import io.jboot.utils.CacheUtil;
import io.jboot.web.controller.annotation.DeleteRequest;
import io.jboot.web.controller.annotation.GetRequest;
import io.jboot.web.controller.annotation.PostRequest;
import io.jboot.web.controller.annotation.RequestMapping;

/**
 * @author 胡高
 * @date 2021/11/11
 */
@RequestMapping(value = "/admin/system/dict")
public class JbsaDictController extends BaseJbsaAdminController {

    private static String SERVICE_NAME = "数据字典";

    private Log LOG = Log.getLog(JbsaDictController.class);

    @Inject
    private JbsaDictService dictService;

    /**
     * 跳转到新增页面
     */
    @GetRequest
    @RequiresPermissions(value = {"system:dict:add"})
    public void add(int parentId) {
        this.LOG.info("跳转到新增{}页面", SERVICE_NAME);

        JbsaDict bean = new JbsaDict();
        bean.setParentId(parentId);

        this.setAttr("bean", bean);
    }

    /**
     * 批量删除功能
     */
    @CacheEvict(name = JbsaConstants.CACHE_NAME_DICT)
    @DeleteRequest
    @RequiresPermissions(value = {"system:dict:del"})
    @JbsaLog("批量删除数据字典")
    public void batchDelete() {
        this.LOG.info("{}批量删除功能：kv={}", SERVICE_NAME, this.getKv());
        Object[] ids = CharSequenceUtil.split(this.get(0), ',').toArray();

        for (Object id : ids) {
            JbsaDict bean = this.dictService.findById(id);
            if (ObjectUtil.isNotNull(bean)) {
                bean.setStatus("del");
                this.dictService.update(bean);
            }
        }

        this.renderAjaxSuccessed();
    }

    /**
     * 删除记录功能
     */
    @CacheEvict(name = JbsaConstants.CACHE_NAME_DICT)
    @DeleteRequest
    @RequiresPermissions(value = {"system:dict:del"})
    @JbsaLog("删除数据字典")
    public void delete() {
        this.LOG.info("{}删除记录功能：kv={}", SERVICE_NAME, this.getKv());

        JbsaDict bean = this.dictService.findById(this.get(0));

        // 记录不存在则报错
        if (ObjectUtil.isNull(bean)) {
            this.renderAjaxFailed("记录不存在！");
            return;
        }

        bean.setStatus("del");

        this.dictService.update(bean);

        this.renderAjaxSuccessed();
    }

    /**
     * 跳转到编辑页面
     */
    @GetRequest
    @RequiresPermissions(value = {"system:dict:edit"})
    public void edit() {
        this.LOG.info("跳转到{}编辑页面", SERVICE_NAME);

        JbsaDict bean = this.dictService.findById(this.get(0));
        this.setAttr("bean", bean);
    }

    /**
     * 跳转到列表页面
     */
    @Override
    @GetRequest
    @RequiresAuthentication
    public void index() {
        this.LOG.info("跳转到{}列表页面", SERVICE_NAME);
    }

    /**
     * 分页查询功能
     * 
     * @param page
     *            页号
     * @param limit
     *            页大小
     * @param sortField
     *            排序字段
     * @param sortType
     *            排序类型：asc或desc
     */
    @GetRequest
    @RequiresPermissions(value = {"system:dict:list"})
    public void list(Integer page, Integer limit, String sortField, String sortType) {
        this.LOG.info("{}分页查询功能：kv={}", SERVICE_NAME, this.getKv());

        /*
         * 建立查询键值对
         */
        Kv para = this.getKv()
            // 标准参数
            .set("sortField", CharSequenceUtil.toUnderlineCase(sortField))
            // 其它参数
            .set("admin", this.getCurrentAdmin())
            ;

        /*
         * 调用服务模块执行查询，并处理缓存
         */
        Page<JbsaDict> pageResult =
            CacheUtil.get(JbsaConstants.CACHE_NAME_DICT, "page_" + para.toJson(), () -> {
                return JbsaDictController.this.dictService.findPageByKv(page, limit, para);
            }, JbsaConstants.CACHE_LIVE_SECONDS);

        /*
         * 返回Ajax调用的Json结果
         */
        this.renderJson(new LayuiPage(pageResult));
    }

    /**
     * 新增或更新记录
     */
    @PostRequest
    @CacheEvict(name = JbsaConstants.CACHE_NAME_DICT)
    @Before(JbsaDictValidator.class)
    @RequiresPermissions(value = {"system:dict:add", "system:dict:edit"})
    @JbsaLog("新增或更新数据字典")
    public void saveOrUpdate(JbsaDict bean) {
        this.LOG.info("新增或更新{}记录：bean={}", SERVICE_NAME, bean);

        JbsaDict exist = this.dictService.findFirstByColumns(
            Columns.create("name", bean.getName()).eq("status", "on").eq("parent_id", bean.getParentId()));

        if (ObjectUtil.isNotNull(exist) && ObjectUtil.isNull(bean.getId())) {
            this.renderAjaxFailed("此名称已经存在!请更换其它名称!");
            return;
        }

        JbsaDict parent = this.dictService.findById(bean.getParentId());

        // 这里引用事务处理是为了方便Ajax模式处理
        boolean success = Db.tx(new IAtom() {

            JbsaAdmin admin = JbsaDictController.this.getCurrentAdmin();
            Date now = new Date();

            @Override
            public boolean run() throws SQLException {
                if (ObjectUtil.isNull(bean.getId())) {
                    /*
                     * 新增记录
                     */
                    // 初始化数据
                    bean.setPathIds(ObjectUtil.isNull(parent) ? ""
                        : parent.getPathIds() + (parent.getPathIds().length() > 0 ? "," : "")
                        + parent.getId());
                    bean.setLayerNum(ObjectUtil.isNull(parent) ? 0 : parent.getLayerNum() + 1);

                    bean.setCreatorId(this.admin.getId());
                    bean.setCreatedTime(this.now);
                    bean.setEditorId(this.admin.getId());
                    bean.setEditedTime(this.now);

                    // 新建记录到数据库
                    JbsaDictController.this.dictService.save(bean);

                } else {
                    /*
                     * 修改记录
                     */
                    JbsaDict exist = JbsaDictController.this.dictService.findById(bean.getId());
                    exist._setAttrs(bean);
                    exist.setEditorId(this.admin.getId());
                    exist.setEditedTime(this.now);

                    // 更新到数据库
                    JbsaDictController.this.dictService.update(exist);
                }

                // 更新父对象的子对象ID列表
                JbsaDictController.this.dictService.updateDictChildredIds(parent);

                return true;
            }
        });

        // 返回Ajax成功
        if (success) {
            this.renderAjaxSuccessed();
        } else {
            this.renderAjaxFailed("操作失败！");
        }
    }

    /**
     * 跳转到记录展示页面
     */
    @GetRequest
    @RequiresPermissions(value = {"system:dict:view"})
    public void view() {
        this.LOG.info("跳转到{}记录展示页面：kv={}", SERVICE_NAME, this.getKv());
        JbsaDict bean = this.dictService.findById(this.get(0));

        this.setAttr("bean", bean);
    }
}
